import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from pylab import mpl
import scipy.stats as stats

# 设置显示中文字体
mpl.rcParams["font.sans-serif"] = ["SimHei"]
# 设置正常显示符号
mpl.rcParams["axes.unicode_minus"] = False

# 1. 加载数据
user_log = pd.read_csv('user_log_format2.csv')
user_info = pd.read_csv('user_info_format1.csv')
train_data = pd.read_csv('train.csv')

# 查看数据的基本信息
print('---data info ---')
for data in [user_log, user_info, train_data]:
    print(data.info())

# 2. 缺失值查看与处理
# 年龄缺失值查看
user_age_miss_pro = (user_info.shape[0] - user_info['age_range'].count()) / user_info.shape[0]
print("年龄缺失率:{:.3}%".format(user_age_miss_pro * 100))
# 年龄未知个数
user_age_un_count = user_info[user_info['age_range'].isna() | (user_info['age_range'] == 0)]['age_range'].count()
print("年龄未知及缺失值个数:{}, 总样本数:{}".format(user_age_un_count, user_info.shape[0]))
# 每个年龄层个数
age_distribution = user_info.groupby(['age_range'])['user_id'].count()
print("每个年龄层的样本数：\n", age_distribution)

# 性别缺失值查看
user_gender_miss_pro = (user_info.shape[0] - user_info['gender'].count()) / user_info.shape[0]
print("性别缺失率:{:.3}%".format(user_gender_miss_pro * 100))
# 性别未知个数
user_gender_un_count = user_info[user_info['gender'].isna() | (user_info['gender'] == 2)]['gender'].count()
print("性别未知及缺失值个数:{}, 总样本数:{}".format(user_gender_un_count, user_info.shape[0]))
# 每个性别个数
gender_distribution = user_info.groupby(['gender'])['user_id'].count()
print("每个性别的样本数：\n", gender_distribution)

# user_log缺失值查看
user_log_missing = user_log.isnull().sum()
print("user_log缺失值统计：\n", user_log_missing)

# 计算user_log中brand_id的缺失率
brand_id_missing_count = user_log['brand_id'].isnull().sum()
brand_id_missing_rate = (brand_id_missing_count / user_log.shape[0]) * 100
print("user_log中brand_id的缺失率：{:.3}%".format(brand_id_missing_rate))

# 缺失值处理
user_info['gender'].fillna(2, inplace=True)  # 用2替换缺失值
user_info['age_range'].fillna(0, inplace=True)  # 用0替换缺失值
user_log['brand_id'].fillna(0, inplace=True)  # 用0替换缺失值

# 3. 数据去重
user_log.drop_duplicates(inplace=True)

# 4. 数据可视化
# 数据分布
label = train_data.groupby('label')['user_id'].count()
print('正负样本的数量：\n', label)
plt.figure(figsize=(12, 6))

plt.subplot(1, 2, 1)
# autopct 保留几位小数 shadow 阴影 explode 偏移量
train_data.label.value_counts().plot(kind='pie', autopct='%1.2f%%', shadow=True, explode=[0, 0.3])
plt.title('正负样本分布')

plt.subplot(1, 2, 2)
# countplot()
sns.countplot('label', data=train_data)
plt.title('正负样本数量')

plt.tight_layout()
plt.show()

# 查看用户情况
# 添加年龄映射
age_dict = {1: '<18', 2: '[18,24]', 3: '[25,29]', 4: '[30,34]', 5: '[35,39]', 6: '[40,49]', 7: '>=50', 8: '>=50', -1: '未知'}
user_info['age_range1'] = user_info['age_range'].map(age_dict)

# 将用户信息和训练数据合并
merged_data = pd.merge(train_data, user_info, on='user_id', how='left')

# 创建一个交叉表，统计每个年龄范围和性别的用户数量
age_gender_count = pd.crosstab(merged_data['age_range1'], merged_data['gender'])

# 绘制热力图
plt.figure(figsize=(10, 6))
sns.heatmap(age_gender_count, annot=True, fmt='d', cmap='YlGnBu', linewidths=.5)
plt.title('年龄范围与性别的分布')
plt.xlabel('性别 (0: 女性, 1: 男性, 2: 未知)')
plt.ylabel('年龄范围')
plt.show()

# 查看影响复购的各种影响因素
# 将用户信息和训练数据合并
merged_data = pd.merge(train_data, user_info, on='user_id', how='left')

# 查看不同商家与复购的关系
print('选取top5店铺\n店铺\t购买次数')
top5_merchants = train_data['merchant_id'].value_counts().head(5)
print(top5_merchants)

# 创建一个新列，标记是否为top5商家
train_data['top5'] = train_data['merchant_id'].apply(lambda x: 1 if x in top5_merchants.index else 0)

# 筛选出top5商家的数据
train_data_top5 = train_data[train_data['top5'] == 1]

# 可视化商家与复购的关系
plt.figure(figsize=(8, 6))
plt.title('商家与复购的关系')
ax = sns.countplot(x='merchant_id', hue='label', data=train_data_top5)
plt.show()

# 性别与复购的关系
plt.figure(figsize=(10, 6))
sns.countplot(x='gender', hue='label', data=merged_data)
plt.title('性别与复购的关系')
plt.xlabel('性别')
plt.ylabel('用户数量')
plt.legend(title='复购情况', labels=['0', '1'])
plt.show()

# 年龄与复购的关系
plt.figure(figsize=(12, 6))
sns.countplot(x='age_range1', hue='label', data=merged_data)
plt.title('年龄与复购的关系')
plt.xlabel('年龄分组')
plt.ylabel('用户数量')
plt.legend(title='复购情况', labels=['0', '1'])
plt.show()